/*
    FreeRTOS V6.1.1 - Copyright (C) 2011 Real Time Engineers Ltd.
*/

/*
	Changes from V3.2.2

	+ Modified the stack sizes used by some tasks to permit use of the 
	  command line GCC tools.
*/

/* Library includes. */
#include <string.h>
#include <stdio.h>

/* Scheduler includes. */
#include "FreeRTOS.h"
#include "task.h"

/* Demo application includes. */
#include "partest.h"
//#include "USB-CDC.h"

/* Demo application includes. */
#include "BasicWEB.h"

/* lwIP includes. */
#include "lwip/api.h" 

/* Hardware specific headers. */
#include "main.h"
#include "Board.h"
#include "AT91SAM7X512.h"

extern "C"
{void *__dso_handle = NULL;}
extern "C"
{void *__cxa_atexit = NULL;}

#define mainWEBSERVER_PRIORITY      ( tskIDLE_PRIORITY + 1 )
/*
 * Setup hardware then start all the demo application tasks.
 */

//TODO: Any global c++ constructor will hang in boot.s
//partTest led_global;

int main( void )
{
	partTest led;
	
	/* Setup the ports. */
	prvSetupHardware();
	
	/* Setup lwIP. */
    vlwIPInit();

	/* Create the lwIP task.  This uses the lwIP RTOS abstraction layer.*/
	sys_thread_new( "WEBSvr", vBasicWEBServer, ( void * ) NULL, lwipBASIC_SERVER_STACK_SIZE, mainWEBSERVER_PRIORITY );


	/* Create the demo USB CDC task. */
	//xTaskCreate( vUSBCDCTask, ( signed char * ) "USB", mainUSB_TASK_STACK, NULL, mainUSB_PRIORITY, NULL );

	/* Start the check task - which is defined in this file. */	
    xTaskCreate( vErrorChecks, ( signed char * ) "Check", configMINIMAL_STACK_SIZE, &led, mainCHECK_TASK_PRIORITY, NULL );

	/* Finally, start the scheduler. 

	NOTE : Tasks run in system mode and the scheduler runs in Supervisor mode.
	The processor MUST be in supervisor mode when vTaskStartScheduler is 
	called.  The demo applications included in the FreeRTOS.org download switch
	to supervisor mode prior to main being called.  If you are not using one of
	these demo application projects then ensure Supervisor mode is used here. */
	vTaskStartScheduler();

	/* Should never get here! */
	return 0;
}
/*-----------------------------------------------------------*/

void EnableResetLine(void)
{
#define	AT91C_RSTC__RESET_KEY	0xA5000000
#define SW1_CTRL_OF_RESET       (1<<30)	// PA30

    // enable SW1 to act as a RESET button by default
	AT91C_BASE_PIOA->PIO_PER = SW1_CTRL_OF_RESET; // Set in PIO mode
	AT91C_BASE_PIOA->PIO_OER = SW1_CTRL_OF_RESET; // Configure in Output	
	AT91C_BASE_PIOA->PIO_CODR = SW1_CTRL_OF_RESET;	// SW1_CTRL_OF_RESET: SW1 should default to /NRST
	
   // enable NRST (the reset line)
	AT91C_BASE_RSTC->RSTC_RMR |= (AT91C_RSTC__RESET_KEY | AT91C_RSTC_URSTEN);
}

void prvSetupHardware( void )
{
	/* When using the JTAG debugger the hardware is not always initialised to
	the correct default state.  This line just ensures that this does not
	cause all interrupts to be masked at the start. */
	AT91C_BASE_AIC->AIC_EOICR = 0;
	
	/* Most setup is performed by the low level init function called from the
	startup asm file.

	Configure the PIO Lines corresponding to LED1 to LED4 to be outputs as
	well as the UART Tx line. */
	AT91C_BASE_PIOB->PIO_PER = LED_MASK; // Set in PIO mode
	AT91C_BASE_PIOB->PIO_OER = LED_MASK; // Configure in Output


	/* Enable the peripheral clock. */
    AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_PIOA;
    AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_PIOB;
	AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_EMAC;

	EnableResetLine();
}

void vErrorChecks( void *pvParameters )
{
	portTickType xDelayPeriod = mainERROR_FLASH_PERIOD;
	portTickType xLastWakeTime;
	partTest* led = (partTest*)pvParameters;
	
	/* The parameters are not used. */
	( void ) pvParameters;

	/* Initialise xLastWakeTime to ensure the first call to vTaskDelayUntil()
	functions correctly. */
	xLastWakeTime = xTaskGetTickCount();

	for( ;; )
	{
		/* Delay until it is time to execute again.  The delay period is
		shorter following an error. */
		vTaskDelayUntil( &xLastWakeTime, xDelayPeriod );
	
		led->vParTestToggleLED( mainCHECK_LED );
	}
}
/*-----------------------------------------------------------*/

void vApplicationIdleHook( void )
{
	static portTickType xLastTx = 0;
	char cTxByte;

	/* The idle hook simply sends a string of characters to the USB port.
	The characters will be buffered and sent once the port is connected. */
	/*if( ( xTaskGetTickCount() - xLastTx ) > mainUSB_TX_FREQUENCY )
	{
		xLastTx = xTaskGetTickCount();
		for( cTxByte = mainFIRST_TX_CHAR; cTxByte <= mainLAST_TX_CHAR; cTxByte++ )
		{
			vUSBSendByte( cTxByte );
		}	
	}*/
}
